const fs = require('fs');
const http = require('http');
const url = require('url');

function load_album_list(cb) {
    fs.readdir("albums/", function(err, files) {
        if(err) {
            cb(err);
            return;
        }
        let only_dirs = [];
        function iterator(index) {
            if(index == files.length) {
                console.log(only_dirs)
                cb(null, only_dirs);
                return;
            }
            fs.stat("albums/" + files[index], (err, stats) => {
                if(err) {
                    cb(err);
                    return;
                }
                if(stats.isDirectory()) {
                    console.log(index);
                    let obj = {name: files[index]};
                    only_dirs.push(obj);
                }
                iterator(index + 1);
            })

        }
        iterator(0);
    })
}

function load_album(album_name, page_num, page_size, cb) {
    console.log("requested album:" + '/albums' + album_name);
    console.log('/albums' + album_name)
    fs.readdir('albums/' + album_name, (err, files)=>{
        console.log(err)
        console.log(files)
        if(err) {
            if(err.code == "ENOENT") {
                cb(no_such_album());
            }else {
                cb(make_error("file_error", JSON.stringify(err)));
            }
            return;
        }

        let only_files = [];
        let path = "albums/" + album_name + "/";
        (function iterator(index) {
            if(index == files.length) {
                let ps;
                ps = only_files.slice(page_size * (page_num-1), page_size);
                let obj = {
                    short_name: album_name,
                    photos: ps
                }
                cb(null, obj);
                return;
            }
            fs.stat(path + files[index], (err, stats)=>{
                if(err) {
                    cb(make_error("file_error", JSON.stringify(err)));
                    return;
                }
                if(stats.isFile()){
                    let obj = {
                        filename: files[index],
                        desc: files[index]
                    }
                    only_files.push(obj);
                }
                iterator(index + 1)
            })
        })(0);
    })
}
function handle_incoming_request(req, res) {
    console.log("incoming request: "+ req.method + " " + req.url);
    req.parsed_url = url.parse(req.url, true);
    let core_url = req.parsed_url.pathname;
    console.log(req.parsed_url);
    if(core_url == '/albums.json') {
        //get albums list
        handle_list_albums(req, res);
    } else if(core_url.substr(core_url.length - 12) == '/rename.json' && req.method.toLowerCase() == 'post') {
        handle_rename_album(req, res)
    } else if(core_url.substr(0, 7) == "/albums" && core_url.substr(core_url.length - 5) == '.json') {
        //get file list
        console.log("handle get album");
        handle_get_album(req, res)
    }else {
        //404
        send_failure(res, 404, invalid_resource())
    }
}

function handle_list_albums(req, res) {
    load_album_list((err, albums)=>{
        if(err) {
            send_failure(res, 500, err);
            return;
        }
        send_success(res, {albums: albums})
    })
}

function handle_get_album(req, res) {
    let parsedUrl = url.parse(req.url, true);
    let getp = parsedUrl.query;
    let page_num = getp.page?getp.page:0;
    let page_size = getp.page_size?getp.page_size:1000;
    let core_url = parsedUrl.pathname;
    if(isNaN(parseInt(page_num))) page_num = 0;
    if(isNaN(parseInt(page_size))) page_size = 0;
    let album_name = core_url.substr(7, core_url.length - 12);
    console.log(album_name);
    load_album(album_name, page_num, page_size, (err, album_contents) => {
        if(err) {
            send_failure(res, 500, err);
            return;
        }
        send_success(res, {album_data: album_contents})
    })
}

function handle_rename_album(req, res) {
    //1. get the album name from the url
    let core_url = req.parsed_url.pathname;
    let parts = core_url.split('/');
    if(parts.length !=  4) {
        send_failure(res, 404, invalid_resource(core_url));
        return;
    }
    let album_name = parts[2];
    //2. get the post data from the request, this will have json
    let json_body = '';
    req.on('readable', () => {
        let d = req.read();
        if(d) {
            if(typeof d == 'string') {
                json_body += d;
            }else if(typeof d == 'object' && d instanceof Buffer) {
                json_body += d.toString('utf8');
            }
        }
    })

    //3.when we have all the post data, make sure we have valid data and try to do the rename
    req.on('end', () => {
        if(json_body) {
            try {
                let album_data = JSON.parse(json_body);
                if(!album_data.album_name) {
                    send_failure(res, 403, missing_data('album_name'));
                    return;
                }
            } catch(e) {
                //invalid body
                send_failure(res, 403, bad_json());
            }
            do_rename();
        }
    })
    //4. perform rename
    // do_rename(album_name, album_data.album_name, (err, results) => {
    //     if(err) {
    //         send_failure(res, 40)
    //     }
    // })
}

function send_failure(res, code, err) {
    let errorCode = err.code? err.code: err.name;
    res.writeHead(code, {"Content-Type": "application/json"});
    res.end(JSON.stringify({error: errorCode, message: err.message}))

}
function send_success(res, data) {
    res.writeHead(200, {"Content-Type": "application/json"})
    res.end(JSON.stringify({error: null, data: data}))
}

function make_error(err, msg) {
    let e = new Error(msg);
    e.code = err;
    return e;
}
function no_such_album() {
    return make_error("no_such_album", "The specified album does not exit")
}
function invalid_resource() {
    return make_error("invalid_resource", "the requested resource does not exit")
}
var s = http.createServer(handle_incoming_request);
s.listen(8080);